package jp.sourceforge.akjrcp.flvtools.search;



import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.ui.FileOverwriteControler;
import jp.sourceforge.akjrcp.youtube.YoutubeViewer;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;


/**
 * This sample class demonstrates how to plug-in a new
 * workbench view. The view shows data obtained from the
 * model. The sample creates a dummy model on the fly,
 * but a real implementation would connect to the model
 * available either in this or another plug-in (e.g. the workspace).
 * The view is connected to the model using a content provider.
 * <p>
 * The view uses a label provider to define how model
 * objects should be presented in the view. Each
 * view can present the same model objects using
 * different labels and icons, if needed. Alternatively,
 * a single label provider can be shared between views
 * in order to ensure that objects of the same type are
 * presented in the same way everywhere.
 * <p>
 */

public class SearchView extends ViewPart {
	public static final String SEARCH_KEYS="search_view.search_keys";
	public static Log log=LogFactory.getLog(SearchView.class);
	public final static String ID=SearchView.class.getName();
	

            
	private TableViewer viewer;
	private Action action1;
	private Action action2;
	private Action doubleClickAction;

	private ArrayList keyList=new ArrayList();
	
	private Button addButton,searchButton;
	private Text inputText;
	/*
	 * The content provider class is responsible for
	 * providing objects to the view. It can wrap
	 * existing objects in adapters or simply return
	 * objects as-is. These objects may be sensitive
	 * to the current input of the view, or ignore
	 * it and always show the same content 
	 * (like Task List, for example).
	 */
	 
	private void remove(List objects) {
		keyList.removeAll(objects);
		YoutubeSearchKey[] obs=(YoutubeSearchKey[]) objects.toArray(new YoutubeSearchKey[0]);
		viewer.refresh();
		updateKeywordData();
	}
	
	private void updateKeywordData() {
		Akj_betasPlugin.getDefault().getPluginPreferences().setValue(SEARCH_KEYS,getSearchKeysFormat());
	}

	private String getSearchKeysFormat() {
		String value="";
		YoutubeSearchKey keys[]=(YoutubeSearchKey[]) keyList.toArray(new YoutubeSearchKey[0]);
		for (int i = 0; i < keys.length; i++) {
			value+=keys[i].toFormat()+"\n";
		}
		return value;
	}

	private void setSearchKeysFormat(){
		keyList.removeAll(keyList);
		String vs=Akj_betasPlugin.getDefault().getPluginPreferences().getString(SEARCH_KEYS);
		log.debug("value="+vs);
		if(vs.equals("")){
			return;
		}
		String formats[]=vs.split("\n");
		
		for (int i = 0; i < formats.length; i++) {
			YoutubeSearchKey key=new YoutubeSearchKey();
			log.info(formats[i]);
			key.setFormat(formats[i]);
			keyList.add(key);
		}
		
	}
	
	class ViewContentProvider implements IStructuredContentProvider {
		public void inputChanged(Viewer v, Object oldInput, Object newInput) {
			log.debug(oldInput+","+newInput);
		}
		public void dispose() {
		}
		public Object[] getElements(Object parent) {
			return keyList.toArray(new YoutubeSearchKey[0]);
		}
	}
	class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
		public String getColumnText(Object obj, int index) {
			return getText(obj);
		}
		public Image getColumnImage(Object obj, int index) {
			return getImage(obj);
		}
		public Image getImage(Object obj) {
			if(useFirefox()){
				return FirefoxUtil.getFirefoxImage();
			}else{
				Program program = Program.findProgram(".html");
				log.info(program.getName());
				
				ImageData data=program.getImageData();
				if(data==null){
					return FirefoxUtil.getOtherImage();
				}
				else{
				return new Image(PlatformUI.getWorkbench().getDisplay(),program.getImageData());
			}
			}
		
			
		}
	}
	class NameSorter extends ViewerSorter {
	}

	/**
	 * The constructor.
	 */
	public SearchView() {

	}
	
	public class KeywordExportListener implements SelectionListener{

		public void widgetSelected(SelectionEvent e) {
			exportText();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
		
			}
		}

	public void exportText(){
		FileDialog dialog=new FileDialog(this.getSite().getShell(),SWT.SAVE);
		dialog.setFilterExtensions(new String[]{"*.csv"});
		String path=dialog.open();
		if(path!=null){
			File tmp=new File(path);
			if(tmp.exists()){
			FileOverwriteControler fileOverwriteControler=new FileOverwriteControler(getSite().getShell(),FileOverwriteControler.MODE_YES_NO_CANCEL);
			boolean overwrite=fileOverwriteControler.canOverwrite(tmp);
			if(!overwrite){
				//log.infogood bye");
				return;
				}
			}
			try {
				String text="";
				int s=keyList.size();
				for (int i = 0; i < s; i++) {
					YoutubeSearchKey ys=(YoutubeSearchKey) keyList.get(i);
					text+=ys.getKeyword()+"\r\n";
				}
				FileUtils.writeStringToFile(new File(path), text);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	public class KeywordInmportListener implements SelectionListener{

		public void widgetSelected(SelectionEvent e) {
			importText();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
		
			}
		}
	public void importText(){
		FileDialog dialog=new FileDialog(this.getSite().getShell(),SWT.OPEN);
		dialog.setFilterExtensions(new String[]{"*.csv"});
		String path=dialog.open();
		if(path!=null){
			try {
				String text=IOUtils.toString(new FileInputStream(new File(path)));
				StringUtils.replace(text, "\r", "");
				String lines[]=text.split("\n");
				for (int i = 0; i < lines.length; i++) {
					if(lines[i].length()>0){
						if(!isAlreadyExistKeyword(lines[i])){
						keyList.add(new YoutubeSearchKey(lines[i],null));
						viewer.refresh();
						//save?
						updateKeywordData();
						}
					}
				}
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public class TextSubmitListener implements SelectionListener{

		public void widgetSelected(SelectionEvent e) {
			addText();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			addText();
			}
		}

		public void addText(){
			String text=inputText.getText();
			if(text.length()>0){
			keyList.add(new YoutubeSearchKey(text,null));
			viewer.refresh();
			//search
			search(text);
			//save?
			updateKeywordData();
			inputText.setText("");
		}
		
	}
	
	public class SearchAction implements SelectionListener{

		public void widgetSelected(SelectionEvent e) {
			
				String v=inputText.getText();
				search(v);
				viewer.refresh();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			// TODO Auto-generated method stub
			
		}
		
	}
	public class SettingMonitor implements IPropertyChangeListener{

		public void propertyChange(PropertyChangeEvent event) {
			log.info(event.getProperty());
			if(event.getProperty().equals(SearchPage.USE_FIREFOX)){
				viewer.refresh();
			}
		}
		
	}
	public void createPartControl(Composite parent) {
		Akj_betasPlugin.getDefault().getPluginPreferences().addPropertyChangeListener( new SettingMonitor());
		setSearchKeysFormat();
		GridLayout gridLayout=new GridLayout(2,false);
		parent.setLayout(gridLayout);
		inputText=new Text(parent,SWT.SINGLE);
		GridData layout1=new GridData(GridData.FILL_HORIZONTAL);
		layout1.horizontalSpan=4;
		inputText.setLayoutData(layout1);
		inputText.addSelectionListener(new TextSubmitListener());
		
		
		searchButton=new Button(parent,SWT.NULL);
		searchButton.setText(Messages.getString("search"));
		searchButton.setToolTipText(Messages.getString("search_tooltip"));
		searchButton.addSelectionListener(new SearchAction());
		
		addButton=new Button(parent,SWT.NULL);
		addButton.setText(Messages.getString("add"));
		addButton.setToolTipText(Messages.getString("add_tooltip"));
		addButton.addSelectionListener(new TextSubmitListener());
		
		
		
		
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		viewer.getTable().setToolTipText(Messages.getString("searchtable_tooltip"));
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setSorter(new NameSorter());
		viewer.setInput(getViewSite());
		GridData layout4=new GridData(GridData.FILL_BOTH);
		layout4.horizontalSpan=2;
		viewer.getControl().setLayoutData(layout4);
		
		Button importButton=new Button(parent,SWT.NULL);
		importButton.setText(Messages.getString("search.import"));
		importButton.addSelectionListener(new KeywordInmportListener());
		Button exportButton=new Button(parent,SWT.NULL);
		exportButton.setText(Messages.getString("search.export"));
		exportButton.addSelectionListener(new KeywordExportListener());
		
		makeActions();
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				SearchView.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(action1);
		manager.add(new Separator());
		//manager.add(action2);
	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(action1);
		//manager.add(action2);
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}
	
	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(action1);
		//manager.add(action2);
	}

	private boolean isAlreadyExistKeyword(String keyword){
		for(int i=0;i<keyList.size();i++){
			YoutubeSearchKey key=(YoutubeSearchKey)keyList.get(i);
			if(key.getKeyword().equals(keyword)){
				return true;
			}
		}
		return false;
	}
	private void makeActions() {
		action1 = new Action() {
			public void run() {
				removeSelection();
			}

			private void removeSelection() {
				remove((((IStructuredSelection)viewer.getSelection()).toList()));
			}

			
		};
		action1.setText(Messages.getString("remove_selections"));
		action1.setToolTipText(Messages.getString("remove_selections"));
		action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
			getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
		
		action2 = new Action() {
			public void run() {
				showMessage("Action 2 executed");
			}
		};
		action2.setText("Action 2");
		action2.setToolTipText("Action 2 tooltip");
		action2.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
				getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
		doubleClickAction = new Action() {
			public void run() {
				
				ISelection selection = viewer.getSelection();
				
				Object obj=((IStructuredSelection)selection).toArray()[0];
				log.debug(obj.getClass().getName());
				String word="";
				Object[] objs = (Object[])((IStructuredSelection)selection).toArray();
				for (int i = 0; i < objs.length; i++) {
					if(objs[i] instanceof YoutubeSearchKey){
					word+=((YoutubeSearchKey)objs[i]).getKeyword();
					if(i!=objs.length-1){
						word+=" ";
					}
					}else{
						//log.info(objs[i].getClass());
					}
				}
				
				search(word);
				
				
				viewer.refresh();
			}
		};
	}
	
	public void search(String keys){
		log.debug("key="+keys);
		String encoded;
		try {
			encoded = URLEncoder.encode(keys,"UTF-8");
			log.debug("encoded="+encoded);
			String baseURL="http://www.youtube.com/results?search_query="+encoded;
			String sort=Akj_betasPlugin.getDefault().getPluginPreferences().getString(SearchPage.MODE_SORT);
			if(!sort.equals(SearchPage.SORT_RELAVANCE)){
				baseURL+="&search_sort="+sort;
			}
			openURL(baseURL);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public boolean useFirefox(){
		return Akj_betasPlugin.getDefault().getPluginPreferences().getBoolean(SearchPage.USE_FIREFOX)
		&& FirefoxUtil.isAvailable();
	}
	public void openURL(String url){
		YoutubeViewer viewer=(YoutubeViewer)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(YoutubeViewer.ID);
		if(viewer!=null){
			viewer.openURL(url);
		}
		/*
		if(useFirefox()){
			FirefoxUtil.openURL(url);
		}else{
			//ie or other default.
			Program program = Program.findProgram(".html");
			
	        if (program != null) {
	        	log.debug(program.getName());
	            program.execute(url);
	        }
		}*/
	}

	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}
	private void showMessage(String message) {
		MessageDialog.openInformation(
			viewer.getControl().getShell(),
			"Sample View",
			message);
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}

	public void widgetSelected(SelectionEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void widgetDefaultSelected(SelectionEvent e) {
		// TODO Auto-generated method stub
		
	}
}